package biz

import (
	"context"
	"errors"
)

// ProductRepo 商品仓储接口，定义商品相关的数据操作方法
// 包括保存、更新、查询、删除、唯一性校验等
type ProductRepo interface {
	Save(ctx context.Context, p *Product) (*Product, error)                // 保存商品
	Update(ctx context.Context, p *Product) (*Product, error)              // 更新商品
	FindByID(ctx context.Context, id int64) (*Product, error)              // 根据ID查询商品
	List(ctx context.Context, page, pageSize int) ([]*Product, int, error) // 分页查询商品列表
	Delete(ctx context.Context, id int64) error                            // 删除商品
	CategoryExists(ctx context.Context, categoryId int64) bool             // 校验分类是否存在
	BrandExists(ctx context.Context, brandId int64) bool                   // 校验品牌是否存在
	NameExists(ctx context.Context, name string) bool                      // 校验商品名唯一性
}

// ProductUsecase 商品用例层，封装商品相关业务逻辑
type ProductUsecase struct {
	repo ProductRepo // 商品仓储接口
}

// NewProductUsecase 创建商品用例实例
func NewProductUsecase(repo ProductRepo) *ProductUsecase {
	return &ProductUsecase{repo: repo}
}

// Create 创建商品，调用仓储层保存数据
func (uc *ProductUsecase) Create(ctx context.Context, p *Product) (*Product, error) {
	// 数据验证
	if err := uc.validateProduct(p); err != nil {
		return nil, err
	}

	// 检查商品名唯一性
	if uc.repo.NameExists(ctx, p.Name) {
		return nil, errors.New("商品名称已存在")
	}

	// 检查分类是否存在
	if !uc.repo.CategoryExists(ctx, p.CategoryID) {
		return nil, errors.New("分类不存在")
	}

	// 检查品牌是否存在
	if !uc.repo.BrandExists(ctx, p.BrandID) {
		return nil, errors.New("品牌不存在")
	}

	return uc.repo.Save(ctx, p)
}

// Update 更新商品
func (uc *ProductUsecase) Update(ctx context.Context, p *Product) (*Product, error) {
	// 数据验证
	if err := uc.validateProduct(p); err != nil {
		return nil, err
	}

	// 检查商品是否存在
	existing, err := uc.repo.FindByID(ctx, p.ID)
	if err != nil {
		return nil, errors.New("商品不存在")
	}

	// 如果名称变更，检查唯一性
	if existing.Name != p.Name && uc.repo.NameExists(ctx, p.Name) {
		return nil, errors.New("商品名称已存在")
	}

	// 检查分类是否存在
	if !uc.repo.CategoryExists(ctx, p.CategoryID) {
		return nil, errors.New("分类不存在")
	}

	// 检查品牌是否存在
	if !uc.repo.BrandExists(ctx, p.BrandID) {
		return nil, errors.New("品牌不存在")
	}

	return uc.repo.Update(ctx, p)
}

// Get 根据ID获取商品
func (uc *ProductUsecase) Get(ctx context.Context, id int64) (*Product, error) {
	if id <= 0 {
		return nil, errors.New("商品ID无效")
	}
	return uc.repo.FindByID(ctx, id)
}

// List 分页获取商品列表
func (uc *ProductUsecase) List(ctx context.Context, page, pageSize int) ([]*Product, int, error) {
	if page <= 0 {
		page = 1
	}
	if pageSize <= 0 || pageSize > 100 {
		pageSize = 20
	}
	return uc.repo.List(ctx, page, pageSize)
}

// Delete 删除商品
func (uc *ProductUsecase) Delete(ctx context.Context, id int64) error {
	if id <= 0 {
		return errors.New("商品ID无效")
	}

	// 检查商品是否存在
	_, err := uc.repo.FindByID(ctx, id)
	if err != nil {
		return errors.New("商品不存在")
	}

	return uc.repo.Delete(ctx, id)
}

// validateProduct 验证商品数据
func (uc *ProductUsecase) validateProduct(p *Product) error {
	if p.Name == "" {
		return errors.New("商品名称不能为空")
	}
	if len(p.Name) > 100 {
		return errors.New("商品名称长度不能超过100个字符")
	}
	if p.Price <= 0 {
		return errors.New("商品价格必须大于0")
	}
	if p.Stock < 0 {
		return errors.New("商品库存不能为负数")
	}
	if p.CategoryID <= 0 {
		return errors.New("分类ID无效")
	}
	if p.BrandID <= 0 {
		return errors.New("品牌ID无效")
	}
	return nil
}

// CategoryExists 校验分类是否存在
func (uc *ProductUsecase) CategoryExists(ctx context.Context, categoryId int64) bool {
	return uc.repo.CategoryExists(ctx, categoryId)
}

// BrandExists 校验品牌是否存在
func (uc *ProductUsecase) BrandExists(ctx context.Context, brandId int64) bool {
	return uc.repo.BrandExists(ctx, brandId)
}

// NameExists 校验商品名唯一性
func (uc *ProductUsecase) NameExists(ctx context.Context, name string) bool {
	return uc.repo.NameExists(ctx, name)
}
